﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;

namespace MonitorManager.Utility
{
    public class DPITool
    {
        //public static decimal GetDpiRatio(Window window)
        //{
        //    var dpi = GetDpi(window, DpiType.Effective);
        //    decimal ratio = 1;
        //    if (dpi > 96)
        //        ratio = (decimal)dpi / 96M;

        //    return ratio;
        //}
        public static decimal GetDpiRatio(Screen screen)
        {
            var dpi = GetDpi(screen, DpiType.Effective);
            decimal ratio = 1;
            if (dpi > 96)
                ratio = (decimal)dpi / 96M;

            //Debug.WriteLine($"Scale: {factor} {ratio}");
            return ratio;
        }

        public static uint GetDpi(Screen screen, DpiType dpiType)
        {
            
            var pnt = new System.Drawing.Point(screen.Bounds.Left + 10, screen.Bounds.Top + 1);
            var mon = MonitorFromPoint(pnt, 2 /*MONITOR_DEFAULTTONEAREST*/);


            try
            {
                uint dpiX, dpiY;
                GetDpiForMonitor(mon, dpiType, out dpiX, out dpiY);
                return dpiX;
            }
            catch
            {
                // fallback for Windows 7 and older - not 100% reliable
               // Graphics graphics = Graphics.FromHwnd(hwnd);
               // float dpiXX = graphics.DpiX;
                //return Convert.ToUInt32(dpiXX);
            }
            return 0;
        }
        private static MONITORENUMPROC monitorEnumProc;
        public delegate bool MONITORENUMPROC(IntPtr hMonitor, IntPtr hdcMonitor, IntPtr lprcMonitor, IntPtr dwData);
        [StructLayout(LayoutKind.Sequential, Size = 8)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
        [StructLayout(LayoutKind.Sequential, Size = 8)]
        public struct MonitorInfos
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public RECT[] Rects;
            public int Count;
        }
        public static MonitorInfos EnumMonitors()
        {
            MonitorInfos mis = new MonitorInfos();
            mis.Rects = new RECT[256];
            mis.Count = 0;
            IntPtr dwData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MonitorInfos)));
            Marshal.StructureToPtr(mis, dwData, true);
            EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, monitorEnumProc, dwData);
            mis = (MonitorInfos)Marshal.PtrToStructure(dwData, typeof(MonitorInfos));
            Marshal.FreeHGlobal(dwData);
            return mis;
        }
        //public static uint GetDpi(Window window, DpiType dpiType)
        //{
        //    var hwnd = new WindowInteropHelper(window).Handle;
        //    return GetDpi(hwnd, dpiType);
        //}

        [DllImport("User32.dll")]
        private static extern IntPtr MonitorFromPoint([In] System.Drawing.Point pt, [In] uint dwFlags);

        [DllImport("Shcore.dll")]
        private static extern IntPtr GetDpiForMonitor([In] IntPtr hmonitor, [In] DpiType dpiType, [Out] out uint dpiX, [Out] out uint dpiY);
        [DllImport("User32.dll")]
        private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr pprcClip, MONITORENUMPROC monitorEnumProc, IntPtr dwData);

        public enum DpiType
        {
            Effective = 0,
            Angular = 1,
            Raw = 2,
        }
    }
}
